#include "sync.h"
#include "printf.h"
#include "riscv.h"
#include "scheduler.h"

// ===== 自旋锁实现 =====

void spinlock_init(spinlock_t* lk, const char* name) {
    lk->locked = 0;
    lk->name = name;
    lk->cpu_id = 0;
}

void spinlock_acquire(spinlock_t* lk) {
    // 关闭中断,防止死锁
    // (持有锁时被中断可能导致死锁)
    uint64_t old_mstatus = r_mstatus();
    w_mstatus(old_mstatus & ~MSTATUS_MIE);
    
    // 自旋等待锁
    while (__sync_lock_test_and_set(&lk->locked, 1) != 0) {
        // 空转等待
    }
    
    // 内存屏障,确保临界区代码不会被重排到锁之前
    __sync_synchronize();
    
    lk->cpu_id = r_mhartid();
}

void spinlock_release(spinlock_t* lk) {
    if (!holding(lk)) {
        printf("[错误] 释放未持有的锁: %s\n", lk->name);
        return;
    }
    
    lk->cpu_id = 0;
    
    // 内存屏障,确保临界区代码不会被重排到锁之后
    __sync_synchronize();
    
    // 释放锁
    __sync_lock_release(&lk->locked);
    
    // 恢复中断
    w_mstatus(r_mstatus() | MSTATUS_MIE);
}

int holding(spinlock_t* lk) {
    return lk->locked && lk->cpu_id == r_mhartid();
}


// ===== 睡眠锁实现 =====

void sleeplock_init(sleeplock_t* lk, const char* name) {
    spinlock_init(&lk->lk, "sleeplock");
    lk->locked = 0;
    lk->name = name;
    lk->pid = 0;
}

void sleeplock_acquire(sleeplock_t* lk) {
    spinlock_acquire(&lk->lk);
    
    // 如果锁已被占用,睡眠等待
    while (lk->locked) {
        // 使用sleep/wakeup机制
        // channel使用sleeplock地址作为唯一标识
        task_sleep((void*)lk);
        
        // 被唤醒后重新检查(可能是虚假唤醒)
    }
    
    // 获取锁
    lk->locked = 1;
    task_t* current = get_current_task();
    lk->pid = current ? current->pid : 0;
    
    spinlock_release(&lk->lk);
}

void sleeplock_release(sleeplock_t* lk) {
    spinlock_acquire(&lk->lk);
    
    if (!lk->locked) {
        printf("[错误] 释放未持有的睡眠锁: %s\n", lk->name);
        spinlock_release(&lk->lk);
        return;
    }
    
    lk->locked = 0;
    lk->pid = 0;
    
    // 唤醒等待的进程
    task_wakeup((void*)lk);
    
    spinlock_release(&lk->lk);
}

int holdingsleep(sleeplock_t* lk) {
    task_t* current = get_current_task();
    return lk->locked && lk->pid == (current ? current->pid : 0);
}


// ===== 条件变量实现 =====

void condvar_init(condvar_t* cv, const char* name) {
    cv->channel = (void*)cv;  // 使用condvar地址作为channel
    cv->name = name;
}

void condvar_wait(condvar_t* cv, spinlock_t* lk) {
    if (!holding(lk)) {
        printf("[错误] condvar_wait必须持有锁\n");
        return;
    }
    
    // 关键: 原子地释放锁并睡眠
    // 这避免了lost wakeup问题
    
    // 1. 释放锁
    spinlock_release(lk);
    
    // 2. 睡眠等待
    task_sleep(cv->channel);
    
    // 3. 被唤醒后重新获取锁
    spinlock_acquire(lk);
}

void condvar_signal(condvar_t* cv) {
    // 唤醒一个等待的进程
    task_wakeup(cv->channel);
}

void condvar_broadcast(condvar_t* cv) {
    // 唤醒所有等待的进程
    task_wakeup(cv->channel);
}


// ===== 信号量实现 =====

void semaphore_init(semaphore_t* sem, int value, const char* name) {
    sem->value = value;
    spinlock_init(&sem->lk, "semaphore");
    sem->name = name;
}

void semaphore_down(semaphore_t* sem) {
    spinlock_acquire(&sem->lk);
    
    // 如果信号量为0,睡眠等待
    while (sem->value == 0) {
        task_sleep((void*)sem);
    }
    
    // 减1
    sem->value--;
    
    spinlock_release(&sem->lk);
}

void semaphore_up(semaphore_t* sem) {
    spinlock_acquire(&sem->lk);
    
    // 加1
    sem->value++;
    
    // 唤醒一个等待的进程
    task_wakeup((void*)sem);
    
    spinlock_release(&sem->lk);
}

